﻿#include "Stack.h"
#include"Date.h"
#include<iostream>
using namespace std;
using std::cout;
using std::endl;
/*
class Date
{
public:
	Date(int year = 1990, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	
	//int Getyear()
	//{
	//	return _year;
	//}

	//重载为成员函数
	//bool operator==(const Date& d1, const Date& d2)
	//❌：原因重载函数的参数太多，操作数的个数要等与参数的个数：除了d还有一个隐藏的this
//bool operator==(const Date& d)//减少为一个参数
//{
//	return this->_year == d._year
//		&& this->_month == d._month 
//		&& _day == d._day;
//	//显示的写this指针
//}

	//赋值重载：带返回值的
	Date& operator=(const Date& d)
	//void operator=(const Date& d)
	{
		if (this!=&d)//避免无用的自我赋值操作
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

private:
	int _year = 1;
	int _month = 1;
	int _day = 1;
};


//**传值返回和引用返回区别**
//传值返回的代价：会拷贝临时变量出来
//引用返回不会拷贝临时变量（提高效率）


//传值返回会生成一个临时对象的拷贝作为返回值
//return d；的这个d不是函数func的返回值，d出函数作用域已经销毁

Date func()
{
	Date d(2024,4,14);//拷贝构造临时对象
	cout << &d << endl;
	return d;
}
//不生成这个临时对象拷贝的方法：
//引用返回：返回的是d的别名(返回的是Date类型的一个引用)
Date& func2()
{
	//Date d(2024, 4, 14);
	static Date d(2024, 4, 14);//改为静态
	cout<< &d <<endl;
	return d;
}
*/

/*
int main()
{
	Date ref = func();
	cout<< &ref <<endl;
	ref.Print();
	//（func：传值拷贝）这里错误的原因：权限的放大;const的常量，赋值要加上const
    Date& ref2 = func2();//用引用接收极大程度上减少拷贝
	cout << &ref2 << endl;
	//本质相当于，ref是d的别名
	//（func:引用返回）可以不加const，因为没有权限的放大：取别名
	ref2.Print();
	//传值没问题/传引用得到的结果就有问题/不是想要的值：出了当前函数的作用域对象已销毁


	return 0;
}
*/


//类中大部分变量为私有的，想要调用,需要重载成全局来解决无法访问的问题
//1，提供这些成员的get与set（修改）
//2，友元
//3，重载为成员函数，全局可访问

//==的运算符重载
//bool operator==(const Date& d1, const Date& d2)
//{
//	return d1._year == d2._year
//		&& d1._month == d2._month
//		&& d1._day == d2._day;
//}

/*
int main()
{
	//Date d3(2024, 4, 14);
	//Date d4(2024, 4, 15);

	////显示调用
	////operator==(d3, d4);
	////重载为成员函数后的调用：
	//d3.operator==(d4);
	////成员函数的调用
	// 
	////直接调用：转换调用：编译会转换成operator==(d3,d4);
	//d3 == d4;

	Date d1(2024, 4, 14);

	//生成一个和d1一样的d2用的：拷贝构造
	//一个已经存在的对象，拷贝构造初始化给另一个未创建初始化的对象
	Date d2(d1);
	//Date d2 = d1;

	Date d4(2024, 5, 1);

	//想让d1变成d4(d4赋给d1)
	d1 = d4;
	//调用的是拷贝构造？？？
	//no❌
	//复制拷贝/赋值重载
	//一个已经存在的对象，拷贝赋值给另一个（不存在构造，也就不叫拷贝构造）
	d1.Print();//完成赋值

	//带返回值的复制拷贝：
	//作用：可以连续赋值简便
	int i, j, k;
	i = j = k = 1;
	//赋值表达式的返回值是左操作数(返回给予赋值的对象的结果)
//    i   j   k

	//连续传值时想拿到中间的j的值：返回*this（当前传）
	cout << i <<j<< k << endl;
	return 0;
}

*/

//Date的测试
void TestDate1()
{
	Date d1(2024, 4, 14);
	Date d2 = d1 + 50;
	d1.Print();
	d2.Print();

	Date d3(2024, 4, 14);
	Date d4 = d3 - 5000;
	d3.Print();
	d4.Print();
	//
	Date d5(2024, 4, 14);
	d5 += -5000;
	d5.Print();
	//结果为：2024-4--4986
	//1，int类型改成size_t也可以
	//2，加等一个负数相当于减，需要在原来的代码做改动，减情况的判断

}

void TeatDate2()
{
	Date d1(2024, 4, 14);

	Date d2 = ++d1;
	//14->15  d2返回++后的值15
	d1.Print();//15
	d2.Print();//15

	Date d3 = d1++;
	//15->16  d3返回++前的值15
	d1.Print();//16
	d3.Print();//15
	
	//可以显示调用：带上参数/不带上：无区别
	d1.operator++(5);//这个参数的值对函数的操作和结果无影响
	d1.Print();//17
	

	Date d4 = --d1;
	//17->16  d2返回--后的值16
	d1.Print();//16
	d4.Print();//16

	Date d5 = d1--;
	//16->15  d3返回--前的值16
	d1.Print();//15
	d5.Print();//16
}

void TestDate3()
{
	Date d1(2025, 7, 30 );
	Date d2(2024, 10, 17);

	int n = d1 - d2;
	cout << n << endl;
}

void TestDate4()
{
	Date d1(2025, 7, 30 );
	Date d2 = d1 + 30000;

	//printf("%d", d1);  //c语言的printf和scanf是有局限性的/只能支持内置类型

	//cin.tie(nullptr);
	//cout.tie(nullptr);//提高输入输出效率
	//ios_base::sync_with_stdio(false);//C++兼容C
	// ******************************************
	// 
	//都有自己的缓冲区/保证交错使用的时候顺序不会被打乱
	/*int n = d2 - d1;
	cout << "1" ;
	printf("2");
	cout << "3" ;
	printf("4");*/
	//

	//形参实参的顺序问题（操作数顺序）

	//流插入（不建议）
	// 函数内部：out<< ...
	// 调用后：cout<< ...
	// ！！传入的参数ostream& out应该是操作符后面的：右操作数
	// 调用的顺序应该为：	d1 << cout;
	// 
	//cout << d1;//出错
	//cout << d2;
	// 
	//d1 << cout;//正确的调用//传入的参数看作是cout才行
	//d1.operator<<(cout);//可以调用
	// 
	////操作数的顺序被迫调换了，不能满足提高可读性的目的

	////结论：流插入想重载为成员函数，可以，但是用起来不符合正常的逻辑和调用的顺序，
	////建议：重载成全局函数！！！！！！1

	//重载成全局，不出错，满足了正确的顺序
	//operator<<(cout,d1)
    cout << d1;
	cout << d2;

	//链式的流插入：返回类型需要是左操作数的同类型ostream&
	cout << d1 << d2;

	//流提取
	//防止输入进错误的日期（不存在的年月日）
	//加个检查：Date.h  48

	//cin >> d1 >> d2;
	cout << d1 << d2;
}

void TestDate5()
{
	//加上const后，不能修改的类，要打印/使用，不能放大权限，
	// 在其函数的结尾 ;前加上const
	const Date d1(2024, 4, 14);
	d1.Print();
	//❌ 下面函数的 *this指针就是d1，d1已经被const修饰了 const Date* this
	// 但是函数内：Date* this,有权限的放大，不能使用
	//修改方式：函数后面加const    -> 	void Print() const;
	// 这里const修饰的是： const Date *this//修饰 *this指针

	/*void Date::Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}*/

	//没有权限的放大，可以使用
	Date d2(2024, 7, 15);
	d2.Print();

	//<的右操作数是const，所以右边是d1的时候可以调用成功/右边是d2不成功
	d1 < d2;
	d2 < d1;
	//解决方案：想使用（不改变操作数值）的操作：全部在函数的结尾加上const：既可以对const的值操作/也可以对非const操作
}   //改变操作数值的操作（如++,+=）不能加上const

//int main()
//{
//	TestDate1();
//	TeatDate2();
//	TestDate3();
//	TestDate4();
//	TestDate5();
//	return 0;
//}


//取地址运算符的重载
class A 
{
public:
	//一般不需要我们实现：除非需要修改返回的真实值
	//构成重载的两个取地址：
	//普通取地址
	A* operator&()
	{
		cout << "A* operator&()" << endl;

		return nullptr;
	}
	//const取地址
	const A* operator&() const
	{
		cout << "const A* operator&() const" << endl;
		return (const A*)this;//不能直接return this，权限的放大
	}

private:
	int _a1=1;
	int _a2=2;
	int _a3=3;
};

//int main()
//{
//	A aa1;
//	const A aa2;
//
//	cout << &aa1 << endl;
//	cout << &aa2 << endl;
//
//	return 0;
//}






































